//#include"glad/glad.h"

#include"mgepch.h"
#include "Application.h"
#include"Input.h"

#include"Log.h"
#include"myMiniEngine/Renderer/Renderer.h"
#include"GLFW/glfw3.h"






namespace myMiniEngine {
#define BIND_EVENT_FN(x) std::bind(&Application::x, this, std::placeholders::_1)

	  Application* Application::instance = nullptr;

	  

	Application::Application() 
	{
		MGE_ASSERT(!instance, "Application alread exists!");
		instance = this;
		window = std::unique_ptr<Window>(Window::Create());
		window->SetEventCallback(BIND_EVENT_FN(OnEvent));

		Renderer::Init();

		m_ImGuiLayer =new ImGuiLayer();
		PushOverlay(m_ImGuiLayer);

		
	}
	Application::~Application()
	{
	}
	void Application::Run() {
		while (m_Running) {
		
			float time = (float)glfwGetTime();
			Timestep ts = time - lastFrameTime;
			lastFrameTime = time;


			for (Layer* layer : layerStack) {
				layer->OnUpdate(ts);
			}

			m_ImGuiLayer->Begin();
			for (Layer* layer : layerStack) {
				layer->OnImGuiRender();
			}

			m_ImGuiLayer->End();

			/*auto [x, y] = Input::GetMousePosition();
			MGE_CORE_TRACE("{0},{1}", x, y);*/

			window->OnUpdate();
		}
	}
	void Application::OnEvent(Event& e)
	{
		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose));
		//MGE_CORE_INFO("{0}",e.ToString()); 

		/*for (Layer* layer : layerStack) {
			layer->OnEvent(e);
		}*/

		/*for (auto itr = layerStack.rbegin(); itr != layerStack.rend(); ++itr)
		{
			if (e.Handled)
				break;
			(*itr)->OnEvent(e);
		}*/

		for (auto it = layerStack.end(); it != layerStack.begin(); )
		{
			(*--it)->OnEvent(e);
			if (e.Handled)
				break;
		}
	}
	void Application::PushLayer(Layer* _layer)
	{
		layerStack.PushLayer(_layer);
		_layer->OnAttach();
	}
	void Application::PushOverlay(Layer* _layer)
	{
		layerStack.PushOverlay(_layer);
		_layer->OnAttach();
	}
	bool Application::OnWindowClose(WindowCloseEvent& e) {
		m_Running = false;
		return true;
	}
}
